<?php
require_once(MODULESPATH . "core/b.object.class.php");
require_once(MODULESPATH . "accounts/business/b.accounts.inc.php");

/**
 * 账户业务层用户类。
 */
class BUser extends BObject implements IBUser{
    /**
     * 需要更换和删除用户ID的对象列表。
     * 列表中的对象需要实现IAdjustUserData接口。
     */
    private $adjustObject = array();
    
    /**
     * 用户首选项的业务层类。
     */
    private $bizPreference = null;
    
    /**
     * 用户数据库访问对象。
     */
    private $daoUser = null;
    
    /**
     * 外部账户映射数据库访问对象。
     */
    private $daoMapping = null;
    
    private $seed = 20030703;
    
    /*- IBUser 接口实现 START -*/
    /*- IInjectEnable 接口实现 START -*/
    /**
     * 设置属性值。
     */
    public function __set($prop, $val){
        if("adjustObject" == $prop){
            array_push($this->$prop, $val);
        }else{
            $this->$prop = $val;
        }
    }
    /*- IInjectEnable 接口实现 END -*/
    
    /**
     * 根据外部映射账号，获取系统用户ID。
     * @param Int $mappingId 外部账号。
     * @param String $type 外部账户映射类型。
     * @return 系统用户ID(未获取到返回-1)。
     */
    public function getUidByMapping($mappingId, $type){
        $result = -1;
        if((strlen(trim($mappingId)) > 0) && (strlen(trim($type)) > 0)){
            $uid = $this->daoMapping->getUidByMapping($mappingId, $type);
            if($uid > 0){
                $result = $uid;
            }else{
                $result = $this->addMappingUser($mappingId, $type);
            }
            if($result && ($result > 0)){
                $this->replaceAnonymity($result);
                $this->setUserCookie($result);
            }
        }
        return $result;
    }
    
    /**
     * 获取当前用户的ID。
     */
    public function getCurrentUserId(){
        $uid = -1;
        $uid = $this->getUserIdByCookie();
        if($uid < 1){
            $uid = $this->addMappingUser();
            $this->setUserCookie($uid);
        }
        $this->updateMappingTime($uid);
        return $uid;
    }
    
    /**
     * 设置用户的首先项。
     * @param String $key 首选项的键。
     * @param String $val 首选项的值。
     */
    public function setPreference($key, $val){
        $result = 0;
        $uid = $this->getUserIdByCookie();
        if(($uid > 0) && (strlen($key) > 0)){
            $result = $this->bizPreference->setPreference($uid, $key, $val, PreferenceType::PRIVATEPREFERENCE);
        }
        return $result;
    }
    
    /**
     * 获取用户的首选项列表。
     * @return 用户的首选项列表。
     */
    public function getPreferences(){
        $result = array();
        $uid = $this->getUserIdByCookie();
        if($uid > 0){
            $result = $this->bizPreference->getPreferences($uid, PreferenceType::ALLPREFERENCE);
        }
        return $result;
    }
    /*- IAdjustUserData 接口实现 START -*/
    /**
     * 更换数据的用户ID。
     * @param Int $oldId 用户旧ID。
     * @param Int $newId 用户新ID。
     * @return 是否操作成功。
     */
    public function replaceByUid($oldId, $newId){
        try{
            //执行注册了的对象的接口，更换数据的用户ID。
            foreach($this->adjustObject as $o){
                $o->replaceByUid($oldId, $newId);
            }
            //删除用户的映射关系
            $this->daoMapping->deleteByUid($oldId);
            //删除用户数据表的数据
            $this->daoUser->deleteById($oldId);
        }catch(Exception $ex){
        }
    }
    
    /**
     * 根据用户ID删除数据。
     * @param Int $uid 用户ID。
     * @return 是否操作成功。
     */
    public function deleteByUid($uid){
        try{
            //执行注册了的对象的接口，更换数据的用户ID。
            foreach($this->adjustObject as $o){
                $o->deleteByUid($oldId, $newId);
            }
            //删除用户的映射关系
            $this->daoMapping->deleteByUid($oldId);
            //删除用户数据表的数据
            $this->daoUser->deleteById($oldId);
        }catch(Exception $ex){
        }
    }
    /*- IAdjustUserData 接口实现 END -*/
    /*- IBUser 接口实现 END -*/
    
    /*- 私有方法 START -*/
    /**
     * 替换匿名用户的数据。
     * @param Int $uid 用户ID。
     * @return 是否操作成功。
     */
    private function replaceAnonymity($uid){
        $anonymity = $this->getUserIdByCookie();
        if(($anonymity > 0) && ($anonymity != $uid)){
            $cookieId = $this->daoMapping->getMappingByUid($anonymity, MappingType::COOKIE);
            if($cookieId > 0){
                $this->replaceByUid($anonymity, $uid);
            }
        }
    }
    
    /**
     * 添加一个账户映射的用户。
     * @param Int $mappingId 外部账号。
     * @param String $type 外部账户映射类型。
     * @return 系统用户ID(未获取到返回-1)。
     */
    private function addMappingUser($mappingId = -1, $type = MappingType::COOKIE){
        $result = -1;
        $uid = $this->daoUser->insert("empty user name", "empty user password", "empty user email");
        if($uid > 0){
            $mappingId = ($mappingId > 0) ? $mappingId : $uid;
            $success = $this->daoMapping->insert($uid, $mappingId, $type);
            if($success){
                $result = $uid;
            }
        }
        return $result;
    }
    
    /**
     * 更新映射账号的使用时间。
     * @param Int $uid 用户编号。
     */
    private function updateMappingTime($uid){
        $isUpdate = false;
        $key = "mapping_user_day_update_" . date("Y-m-d");
        $users = $this->cache->get($key);
        if($users == null){
            $users = array($uid);
            $isUpdate = true;
        }elseif(!in_array($uid, $users)){
            array_push($users, $uid);
            $isUpdate = true;
        }
        if($isUpdate){
            $expire = 60 * 60 * 24 * 2;//2天
            $this->cache->set($key, $users, $expire);
            $this->daoMapping->updateMappingTime($uid);
        }
    }
    
    /**
     * 设置用户标识的Cookie。
     * @param Int $uid 用户编号。
     */
    private function setUserCookie($uid){
        $name = "stud";
        $val = $this->encode($uid);
        $expire = time() + 60 * 60 * 24 * 30 * 120;
        $path = "/";
        setcookie($name, $val, $expire, $path);        
    }
    
    /**
     * 从Cookie中获取用户编号。
     * @return Int 用户编号。
     */
    private function getUserIdByCookie(){
        $result = -1;
        $name = "stud";
        $val = $_COOKIE[$name];
        if($val && strlen($val) > 0){
            $uid = $this->decode(trim($val));
            if($uid > 0){
                $result = $uid;
            }
        }
        return $result;
    }
    
    /**
     * 对整数进行编码。
     * @param Int $int 需要编码的整数。
     * @return String 编码后的字符串。
     */
    private function encode($int){
        return (dechex($int + $this->seed));
    }
    
    /**
     * 对整数进行编码。
     * @param String $str 需要编码的整数。
     * @return Int 编码后的字符串。
     */
    private function decode($str){
        return (hexdec($str) - $this->seed);
    }
    /*- 私有方法 END -*/
}
?>
